package org.rubyforge.javatestingguff;

import java.lang.reflect.Field;

public class Reflect {
    public static void setField(Object object, String fieldName, Object value) {
        new Reflect().traverseClassHierarchy(object, fieldName, value, new Setter());
    }

    private Object traverseClassHierarchy(Object object, String fieldName, Object value, Executor executor) {
        Class currentClass = object.getClass();
        while (currentClass != Object.class) {
            try {
                Field field = currentClass.getDeclaredField(fieldName);
                field.setAccessible(true);
                try {
                    return executor.execute(object, value, field);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            } catch (NoSuchFieldException ignore) {
                currentClass = currentClass.getSuperclass();
            }
        }
        String message = String.format("%s not found on class : %s or value of type %s is incorrect", fieldName, objectClassName(object), objectClassName(value));
        throw new RuntimeException(message);
    }

    private String objectClassName(Object o) {
        return o == null ? "NULL" : o.getClass().getSimpleName();
    }

    interface Executor {
        Object execute(Object object, Object value, Field field) throws IllegalAccessException;
    }

    private static class Setter implements Executor {
        public Object execute(Object object, Object value, Field field) throws IllegalAccessException {
            field.set(object, value);
            return null;
        }
    }
}